home *** CD-ROM | disk | FTP | other *** search
/ Way Cool Games 2 / Quantum Axcess Way Cool Games Too.iso / games / yalife / source / cell.cpp next >
Encoding:
C/C++ Source or Header  |  1993-09-08  |  8.4 KB  |  315 lines

  1. // (c) Jean MICHEL June 1993 -- any modifications must be signaled to the
  2. // author
  3.  
  4. // cell.cpp: classes to compute life generations. This is completely
  5. // independant from windows, and can be used Con any system
  6.  
  7. #include "cell.h"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <io.h>
  11. #include <string.h>
  12. #include "efns.h"
  13. #define MAXCELLS 16000
  14. #define INFINI 0xfffdfffal
  15. static cell_type temp[MAXCELLS];
  16.  
  17. static cell_type *copy(cell_type *pw,int pop)
  18. { cell_type *v=new cell_type[pop+1];
  19.   for(int i=0;i<pop;i++)v[i]=pw[i];
  20.   v[i]=INFINI;
  21.   return v;
  22. }
  23.  
  24. cellpop::cellpop(cellpop&w){pop=w.pop;v=copy(w.v,pop);}
  25.  
  26. void cellpop::clear_pop(){delete[] v;v=copy(NULL,pop=0);}
  27.  
  28. cellpop::cellpop(){v=NULL;pop=0;}
  29.  
  30. void cellpop::operator=(const cellpop& w)
  31. {if(v)delete[] v;v=copy(w.v,pop=w.pop);}
  32.  
  33. cellpop::~cellpop(){if(v)delete[] v;}
  34.  
  35. cellpop::cellpop(int lg)
  36. { pop=lg;
  37.   v=new cell_type[pop+1];
  38.   for(int i=0;i<pop;i++)v[i]=cell_type(i,0);
  39.   v[i]=INFINI;
  40. }
  41.  
  42. BOOL cellpop::operator==(cellpop& w)
  43. { if(pop!=w.pop)return FALSE;
  44.   for(int i=0;i<pop;i++)if(v[i]!=w.v[i])return FALSE;
  45.   return TRUE;
  46. }
  47.  
  48. BOOL cellpop::in(cell_type c)
  49. { for(int i=0;i<pop;i++)if(v[i]==c)return TRUE;
  50.   return FALSE;
  51. }
  52.  
  53. void cellpop::nextgen(cellpop& w)/* v=nextgen from w */
  54. { INTCELL *ind[9]/* indexes in w for neighb*/;
  55.   static INTCELL neighb[9]; // neighbours
  56.   for(int i=0;i<9;i++){neighb[i]=0;ind[i]=(INTCELL *)w.v;}
  57.   static long d[9]={-BASE-1,-BASE,1-BASE,-1,0,1,BASE-1,BASE,BASE+1};
  58.   /* relative position of neighbours */
  59.   INTCELL x,lim=INFINI+d[0];
  60.   int iv=0;
  61.   for(INTCELL z=0/* previous cell */;z<lim;z=x)
  62.   { INTCELL *n=neighb;int sum=0;
  63.     x=INFINI; // will become current cell
  64.     for (i=0;i<9;i++,n++)
  65.     { if(*n==z)*n=d[i]+*ind[i]++;
  66.       if(*n<x){x=*n;sum=1;}
  67.       else if(*n==x)sum++;
  68.     }
  69.     if(sum==3 ||(sum==4 && neighb[4]==x))
  70.     { if(iv>=MAXCELLS)
  71.       { efns(WARNING_,"%d: too many cells",MAXCELLS);
  72.     delete[]v;v=NULL;
  73.     return;
  74.       }
  75.       temp[iv++]=cell_type(x);
  76.     }
  77.   }
  78.   delete[]v;v=copy(temp,pop=iv);
  79. }
  80.  
  81. static int compar(const void *a,const void *b)
  82. { unsigned long x=*(unsigned long *)a,y=*(unsigned long *)b;
  83.   return x<y?-1:(x>y?1:0);}
  84.  
  85. void cellpop::transform(char orientation)
  86. { int dirx=orientation&0x1?-1:1,diry=orientation&0x2?-1:1;
  87.   BOOL rot=orientation&0x4;
  88.   for(int i=0;i<pop;i++)
  89.   v[i]=cell_type(dirx*(rot?v[i].celly():v[i].cellx()),
  90.          diry*(rot?v[i].cellx():v[i].celly()));
  91.   qsort(v,pop,sizeof(cell_type),compar);
  92. }
  93.  
  94. void cellpop::add(cellpop&w,cellpop &shape,cell_type offset,int mode)
  95. { int iv=0,iw=0;
  96.   for(int is=0;is<shape.pop;is++)
  97.   { cell_type c=shape.v[is]+offset;
  98.     while(w.v[iw]<c)temp[iv++]=w.v[iw++];
  99.     if(w.v[iw]>c){if(mode!=LAY_OFF)temp[iv++]=c;}
  100.     else if(mode==LAY_ON)temp[iv++]=w.v[iw++];
  101.     else iw++;
  102.   }
  103.   while(iw<w.pop)temp[iv++]=w.v[iw++];
  104.   v=copy(temp,pop=iv);
  105. }
  106.  
  107. cell_type cellpop::lastx(void)
  108. { cell_type res;int x=-cell_type(INFINI).cellx();
  109.   for(int i=0;i<pop;i++)
  110.     if(v[i].cellx()>=x){x=v[i].cellx();res=v[i];}
  111.   return res;
  112. }
  113.  
  114. cell_type cellpop::firstx(void)
  115. { cell_type res;int x=cell_type(INFINI).cellx();
  116.   for(int i=0;i<pop;i++)
  117.     if(v[i].cellx()<x){x=v[i].cellx();res=v[i];}
  118.   return res;
  119. }
  120.  
  121. cell_type cellpop::firsty(void)
  122. { cell_type res;int y=cell_type(INFINI).cellx();
  123.   for(int i=0;i<pop;i++)
  124.     if(v[i].celly()<y){y=v[i].celly();res=v[i];}
  125.   return res;
  126. }
  127.  
  128. cell_type cellpop::lasty(void)
  129. { cell_type res;int y=-cell_type(INFINI).cellx();
  130.   for(int i=0;i<pop;i++)
  131.     if(v[i].celly()>=y){y=v[i].celly();res=v[i];}
  132.   return res;
  133. }
  134.  
  135. void cellpop::erase_rect(cell_type start,cell_type end)
  136. { int y=0;
  137.   for(int x=0;x<pop;x++)
  138.      if(v[x].cellx()<start.cellx() || v[x].cellx()>=end.cellx() ||
  139.     v[x].celly()<start.celly() || v[x].celly()>=end.celly()) v[y++]=v[x];
  140.   v[y]=INFINI;
  141.   pop=y;
  142. }
  143.  
  144. void cellpop::save_rect(char *FileName,cell_type start,cell_type end)
  145. { FILE *fp=fopen(FileName,"w");
  146.   int x=start.x,y=start.y;
  147.   if(fp==NULL){ efns(WARNING_|FILE_,FileName);return;}
  148.   for(int i=0;i<pop;i++)
  149.     if(v[i].cellx()>=start.cellx() && v[i].cellx()<end.cellx() &&
  150.        v[i].celly()>=start.celly() && v[i].celly()<end.celly())
  151.     { for(;y<v[i].y;y++){fprintf(fp,"\n");x=start.x;}
  152.       for(;x<v[i].x;x++)fprintf(fp," ");
  153.       fprintf(fp,"o");x++;
  154.     }
  155.   fprintf(fp,"\n");
  156.   fclose(fp);
  157. }
  158.  
  159. void cellpop::save(char *FileName)
  160. { save_rect(FileName,cell_type(firstx().cellx(),firsty().celly()),
  161.              cell_type(1+lastx().cellx(),1+lasty().celly()));
  162. }
  163.  
  164. cellpop::cellpop(char *string)
  165. { pop=0;v=0;
  166.   int x=0,y=0;
  167.   for(char *s=string;*s;s++)
  168.   switch(*s)
  169.   { case '\n':y++;x=0;break;
  170.     case '\r':break;
  171.     case ' ':case '.':x++;break;
  172.     case '$':x+=10;break;
  173.     case '\t': x+=8-x%8;break;
  174.     case 'o':case 'O':
  175.       if(pop==MAXCELLS){efns(WARNING_,"%d: too many cells",MAXCELLS);return;}
  176.       temp[pop++]=cell_type(x,y);
  177.       x++;break;
  178.     default: efns(WARNING_,"invalid data in string <%.15s>",
  179.                                                        s-5<string?string:s-5);
  180.              return;
  181.   }
  182.   v=copy(temp,pop);
  183. }
  184.  
  185. cellpop readfile(char *FileName)
  186. { cellpop res;
  187.   FILE *f=fopen(FileName,"rb");
  188.   if(f==NULL)
  189.   { efns(WARNING_|FILE_,FileName);
  190.     return res;
  191.   }
  192.   long flen=filelength(fileno(f));
  193.   if(flen>65534u)
  194.   { efns(WARNING_,"file `%s' too big: %ld bytes",FileName,flen) ;
  195.     fclose(f);return res;
  196.   }
  197.   char *s=new char[(unsigned)flen];
  198.   if(flen!=fread(s,1,(unsigned)flen,f))
  199.   { efns(WARNING_|FILE_,FileName);
  200.     delete[]s;fclose(f);return res;
  201.   }
  202.   fclose(f);
  203.   s[flen]=0; res=cellpop(s);
  204.   delete[]s;
  205.   return res;
  206. }
  207.  
  208.  
  209. struct named_shape
  210. {   char *name;
  211.     cellpop shape;
  212.     named_shape *next,*prev;
  213. };
  214. static named_shape *shapeptr=NULL;
  215.  
  216. static int shapeidx=-1;
  217.  
  218. char *getshapename(int i)
  219. { if(!shapeptr)return NULL;
  220.   while(i>shapeidx && shapeptr->next)
  221.   { shapeidx++;shapeptr=shapeptr->next;}
  222.   if(i>shapeidx)return NULL;
  223.   while(i<shapeidx && shapeptr->prev)
  224.   { shapeidx--;shapeptr=shapeptr->prev;}
  225.   if(i<shapeidx)return NULL;
  226.   return shapeptr->name;
  227. }
  228.  
  229. cellpop getshape(int i)
  230. { char *s=getshapename(i);
  231.   return shapeptr->shape;
  232. }
  233.  
  234. #define MAXNAME 30
  235. void readshapelib(char *FileName)
  236. { FILE *f=fopen(FileName,"rb");
  237.   int line=1,c;
  238.   char name[MAXNAME+1];
  239.   named_shape *oldptr=NULL;
  240.   if(f==NULL)
  241.   { efns(WARNING_|FILE_,FileName);
  242.     return;
  243.   }
  244.   if(shapeptr)
  245.   { while(shapeptr->next)
  246.     { shapeidx++;shapeptr=shapeptr->next;}
  247.     oldptr=shapeptr;
  248.   }
  249.   while((c=getc(f))!=EOF)switch(c)
  250.   { case '|': while((c=getc(f))!=EOF && c!='\n');line++;break;
  251.     case '[': for(char *n=name;(c=getc(f))!=']';n++)
  252.          { if(n>=name+MAXNAME)
  253.            { efns(WARNING_,"error in %s line %d: name too long (>%d chars)",
  254.             FileName,line,MAXNAME);
  255.          goto fin;
  256.            }
  257.            if(c==EOF)
  258.            { efns(WARNING_,"error in %s line %d: end of file in name",
  259.             FileName,line);
  260.          goto fin;
  261.            }
  262.            if(c=='\n')
  263.            { efns(WARNING_,"error in %s line %d: line break in name",
  264.             FileName,line);
  265.          goto fin;
  266.            }
  267.            *n=c;
  268.          }
  269.          while((c=getc(f))==' ' || c=='\t' || c=='\r');
  270.          if(c!='\n')
  271.          { efns(WARNING_,"error in %s: garbage follows name line %d",
  272.           FileName,line);
  273.            goto fin;
  274.          }
  275.          else line++;
  276.          *n=0;
  277.          cellpop w;
  278.              int x=0,y=0;
  279.              while(strchr("\n\r .$\toO",c=getc(f)))switch(c)
  280.          { case '\n':y++;x=0;line++;break;
  281.            case '\r':break;
  282.            case ' ':case '.':x++;break;
  283.            case '$':x+=10;break;
  284.            case '\t': x+=8-x%8;break;
  285.            case 'o':case 'O':
  286.            if(w.pop==MAXCELLS)
  287.            { efns(WARNING_,"error in %s line %d: too many cells(%d)",
  288.                          FileName,line,MAXCELLS);
  289.          goto fin;
  290.                }
  291.            temp[w.pop++]=cell_type(x,y);
  292.            x++;break;
  293.            default: efns(WARNING_,"error in %s line %d: invalid data",
  294.                                  FileName, line);
  295.             goto fin;
  296.          }
  297.          ungetc(c,f);
  298.              w.v=copy(temp,w.pop);
  299.          named_shape *temp=new named_shape;
  300.              if(shapeptr)shapeptr->next=temp;
  301.          temp->prev=shapeptr;
  302.              shapeptr=temp;
  303.              shapeidx++;
  304.              shapeptr->next=NULL;
  305.              shapeptr->name=strdup(name);
  306.              shapeptr->shape=w;
  307.   }
  308.   fin: fclose(f);
  309.   if(oldptr)
  310.   { oldptr->next->prev=NULL;
  311.     for(;oldptr;oldptr=oldptr->prev)shapeidx--;
  312.   }
  313.   return;
  314. }
  315.